package com.lipei.vrp.imp;

import java.text.DecimalFormat;
import java.util.ArrayList;

import com.lipei.vrp.AlgorithmType;
import com.lipei.vrp.Context;
import com.lipei.vrp.IAlgorithm;
import com.lipei.vrp.IAlgorithmCreator;
import com.lipei.vrp.Opt;
import com.lipei.vrp.ResultType;

public class OriginalVRP implements IAlgorithmCreator {

	private class Impl implements IAlgorithm {
		private int numberof_vehicle;
		private Double upperbound;

		public Impl(String[] args) {
			if (args.length > 4) {
				throw new RuntimeException("argument don't match.");
			}
			numberof_vehicle = Integer.parseInt(args[2]);
			if (args.length == 4) {
				upperbound = Double.parseDouble(args[3]);
			} else {
				upperbound = null;
			}
		}

		@Override
		public ArrayList<String> generateCommand(String vrppath) {
			ArrayList<String> commands = new ArrayList<String>();
			commands.add(Context.orgvrppath);
			commands.add("-F");
			commands.add(vrppath);
			commands.add("-N");
			commands.add(Integer.toString(numberof_vehicle));

			DecimalFormat format = new DecimalFormat("0.000");
			String command = Context.orgvrppath + " -F \"" + vrppath + "\" -N "
					+ numberof_vehicle;
			if (upperbound != null) {
				commands.add("-u");
				commands.add(format.format(upperbound));
			}
			return commands;
		}

		@Override
		public Opt parse(ArrayList<String> list, boolean timeout, boolean failed) {
			ResultType resulttype = null;
			if (timeout) {
				resulttype = ResultType.OT;
			}
			if (failed) {
				resulttype = ResultType.FAIL;
			}
			for (String string : list) {
				if (string.contains("Optimal Solution Found")) {
					resulttype = ResultType.OPT;
					break;
				}
				if (string.contains("Branch and Cut Finished")) {
					resulttype = ResultType.NUL;
					break;
				}
				if (string.contains("Max num of cuts in CP pool exceeded")
						&& timeout) {
					resulttype = ResultType.MCOT;
				}
			}
			int i = list.size() - 1;
			for (; i >= 0; i--) {
				String line = list.get(i);
				if (line.contains("Solution Cost")) {
					break;
				}
			}

			Opt opt;
			if (i >= 0) {
				ArrayList<String> sublines = new ArrayList<String>();
				int cost = i;
				i += 2;

				for (; i < list.size(); i++) {
					sublines.add(list.get(i));
				}
				opt = Opt.readroute(sublines);
				opt.resulttype = resulttype;
				String costline = list.get(cost);
				opt.cost = Double.parseDouble(costline.substring(15));
			} else {
				opt = new Opt();
				opt.resulttype = resulttype;
			}

			opt.algtype = AlgorithmType.VRP;
			return opt;
		}
	}

	public static IAlgorithmCreator createIns() {
		return new OriginalVRP();
	}

	@Override
	public IAlgorithm argsCheck(String[] args) {
		return new Impl(args);
	}

}
